﻿/* 
 * Copyright (c) 2010 Letwory Interactive
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * -- Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * -- Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * Original contributor: Nathan Letwory
 */

using System;

namespace VerseSharp
{
    public delegate void ObjectTransformPosReal64Callback(ObjectTransformPosReal64Command command);

    public class ObjectTransformPosReal64Command : IVerseCommand
    {
        public CommandID ID { get { return CommandID.ObjectTransformPosReal64; } }
        public uint NodeID;
        public uint TimeS;
        public uint TimeF;
        public byte Mask;
        public double[] Pos = null;
        public double[] Speed = null;
        public double[] Accel = null;
        public double[] DragNormal = null;
        public double Drag = double.NaN;

        public void Deserialize(byte[] source, ref int pos)
        {
            double x, y, z;
            NodeID = Utils.GetUInt32(source, ref pos);
            TimeS = Utils.GetUInt32(source, ref pos);
            TimeF = Utils.GetUInt32(source, ref pos);

            Mask = (byte)source[pos++];

            x = Utils.GetReal64(source, ref pos);
            y = Utils.GetReal64(source, ref pos);
            z = Utils.GetReal64(source, ref pos);

            SetPos(x, y, z);

            if ((Mask & 1) == 1)
            {
                x = Utils.GetReal64(source, ref pos);
                y = Utils.GetReal64(source, ref pos);
                z = Utils.GetReal64(source, ref pos);
                SetSpeed(x, y, z);
            }
            if ((Mask & 2) == 2)
            {
                x = Utils.GetReal64(source, ref pos);
                y = Utils.GetReal64(source, ref pos);
                z = Utils.GetReal64(source, ref pos);
                SetAccel(x, y, z);
            }
            if ((Mask & 4) == 4)
            {
                x = Utils.GetReal64(source, ref pos);
                y = Utils.GetReal64(source, ref pos);
                z = Utils.GetReal64(source, ref pos);
                SetDragNormal(x, y, z);
            }
            if ((Mask & 8) == 8)
            {
                Drag = Utils.GetReal64(source, ref pos);
            }
        }

        public void SetPos(double x, double y, double z)
        {
            if (Pos == null)
            {
                Pos = new double[3];
            }
            Pos[0] = x;
            Pos[1] = y;
            Pos[2] = z;
        }

        public void SetSpeed(double x, double y, double z)
        {
            if (Speed == null)
            {
                Speed = new double[3];
            }
            Speed[0] = x;
            Speed[1] = y;
            Speed[2] = z;
        }

        public void SetAccel(double x, double y, double z)
        {
            if (Accel == null)
            {
                Accel = new double[3];
            }
            Accel[0] = x;
            Accel[1] = y;
            Accel[2] = z;
        }

        public void SetDragNormal(double x, double y, double z)
        {
            if (DragNormal == null)
            {
                DragNormal = new double[3];
            }
            DragNormal[0] = x;
            DragNormal[1] = y;
            DragNormal[2] = z;
        }

        public void Serialize(byte[] destination, ref int pos)
        {
            Utils.PutUInt32(destination, ref pos, NodeID);
            Utils.PutUInt32(destination, ref pos, TimeS);
            Utils.PutUInt32(destination, ref pos, TimeF);

            int maskPos = pos;
            pos++;

            Utils.PutReal64(destination, ref pos, Pos[0]);
            Utils.PutReal64(destination, ref pos, Pos[1]);
            Utils.PutReal64(destination, ref pos, Pos[2]);

            if (Speed != null)
            {
                destination[maskPos] |= 1;
                Utils.PutReal64(destination, ref pos, Speed[0]);
                Utils.PutReal64(destination, ref pos, Speed[1]);
                Utils.PutReal64(destination, ref pos, Speed[2]);
            }
            if (Accel != null)
            {
                destination[maskPos] |= 2;
                Utils.PutReal64(destination, ref pos, Accel[0]);
                Utils.PutReal64(destination, ref pos, Accel[1]);
                Utils.PutReal64(destination, ref pos, Accel[2]);
            }
            if (DragNormal != null)
            {
                destination[maskPos] |= 4;
                Utils.PutReal64(destination, ref pos, DragNormal[0]);
                Utils.PutReal64(destination, ref pos, DragNormal[1]);
                Utils.PutReal64(destination, ref pos, DragNormal[2]);
            }
            if (Drag != double.NaN)
            {
                destination[maskPos] |= 8;
                Utils.PutReal64(destination, ref pos, Drag);
            }
        }
    }
}
